﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.StorageClient;
using nwrole.toolbox.mailservice.EmailSerialization;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

namespace nwrole.toolbox.mailservice
{
    public class AzureCloudQueueClient
    {
        public string StorageAccount { get; set; }
        public string LargeMessageBlobContainerName { get; set; }
        public string QueueName { get; set; }
        public string ErrorQueueName { get; set; }

        private CloudStorageAccount _account;
        protected CloudStorageAccount Account
        {
            get
            {
                if (_account == null) _account = CloudStorageAccount.Parse(this.StorageAccount);
                return _account;
            }
            set { _account = value; }
        }

        private CloudQueue _queue;
        protected CloudQueue Queue
        {
            get
            {
                if (_queue == null)
                    _queue = Account.CreateCloudQueueClient().GetQueueReference(this.QueueName);
                _queue.CreateIfNotExist();
                return _queue;
            }
            set { _queue = value; }
        }

        private CloudBlobContainer _largeMessageBlobContainer;
        protected CloudBlobContainer LargeMessageBlobContainer
        {
            get
            {
                if (_largeMessageBlobContainer == null)
                {
                    _largeMessageBlobContainer = Account.CreateCloudBlobClient().GetContainerReference(this.LargeMessageBlobContainerName);
                }
                return _largeMessageBlobContainer;
            }
            set { _largeMessageBlobContainer = value; }
        }

        protected void SendToErrorQueue(CloudQueueMessage message)
        {
            var queue = Account.CreateCloudQueueClient().GetQueueReference(this.ErrorQueueName);
            queue.AddMessage(message);
        }

        public AzureCloudQueueClient(string storageAccount, string largeMessageBlobContainerName, string queueName)
        {
            StorageAccount = storageAccount;
            LargeMessageBlobContainerName = largeMessageBlobContainerName;
            QueueName = queueName;
        }

        public CloudQueueMessage DequeueMessage(out SerializeableMailMessage msg)
        {
            msg = null;

            CloudQueueMessage message = this.Queue.GetMessage(new TimeSpan(0, 1, 0));
            if (message == null)
            {
                return null;
            }

            // Does the message contain a guid?            
            Guid? guid = null;
            try { 
                guid = new Guid(message.AsString); 
            }
            catch (Exception) 
            {
                return null;
            }

            if (guid != null)
            {
                var blob = this.LargeMessageBlobContainer.GetBlobReference(guid.ToString());
                if (blob != null)
                {
                    byte[] bytes = Convert.FromBase64String(blob.DownloadText());

                    using (var ms = new MemoryStream(bytes))
                    {
                        msg = (SerializeableMailMessage)new BinaryFormatter().Deserialize(ms);
                    }

                    /*using (MemoryStream stream = new MemoryStream(blob.DownloadByteArray()))
                    {
                        DataContractSerializer serializer = new DataContractSerializer(typeof(SerializeableMailMessage));
                        msg = (SerializeableMailMessage)serializer.ReadObject(stream);
                    }*/

                    blob.DeleteIfExists();
                }                    
            }

            this.Queue.DeleteMessage(message);

            return message;
        }

        /*public void DeleteMessage(CloudQueueMessage message)
        {
            // Does the message contain a guid? If so delete the blob
            if (message.AsBytes.Length == 16)
            {
                Guid? guid = null;
                try 
                { 
                    guid = new Guid(message.AsString); 
                }
                catch (Exception) 
                {
                    return;
                }

                if (guid != null)
                {
                    this.LargeMessageBlobContainer.GetBlobReference(guid.ToString()).DeleteIfExists();
                }
            }

            this.Queue.DeleteMessage(message);
        }*/

        public Guid EnqueueMessage(SerializeableMailMessage msg)
        {
            var guid = Guid.NewGuid();

            using (MemoryStream stream = new MemoryStream())
            {
                new BinaryFormatter().Serialize(stream, msg);
                string s = Convert.ToBase64String(stream.ToArray());

                /*DataContractSerializer serializer = new DataContractSerializer(msg.GetType());
                serializer.WriteObject(stream, msg);
                stream.Position = 0;*/
                this.LargeMessageBlobContainer.GetBlobReference(guid.ToString()).UploadText(s);
                //this.LargeMessageBlobContainer.GetBlobReference(guid.ToString()).UploadFromStream(stream);
                this.Queue.AddMessage(new CloudQueueMessage(guid.ToString()));
            }

            // Large messages has to be saved in blob storage
            /*            if (message.Length > 8000)
                        {
                            var guid = Guid.NewGuid().Tostring();
                            this.LargeMessageBlobContainer.GetBlobReference(guid).Up.UploadText(message);

                            this.Queue.AddMessage(new CloudQueueMessage(guid));
                        }
                        else
                        {
                            this.Queue.AddMessage(new CloudQueueMessage(message));
                        } */

            return guid;
        }
    }
}
